﻿using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;

namespace FolderSynchronizer
{
	/// <summary>
	/// Класс, содержащий методы получения xml файлов о файлах в заданных папка и файлах, которые отличаются в исходной и конечной папке.
	/// </summary>
	public class ReceptionFolderInformation
	{
		private string source;
		private string target;
		private List<FileInformation> filesInSourceDir;
		private List<FileInformation> filesFromRelease;
	    private string[] excludeFolders;
		/// <summary>
		/// Конструктор класса.
		/// </summary>
		/// <param name="source">Путь к исходной папке.</param>
		/// <param name="target">Путь к конечной папке.</param>
		/// <param name="filesFromRelease">Список файлов из релиза.</param>
		public ReceptionFolderInformation(string source, string target, List<FileInformation> filesFromRelease = null, string[] excludeFolders = null)
		{
			this.source = source;
			this.target = target;
			this.filesFromRelease = filesFromRelease;
		    this.excludeFolders = excludeFolders;
		}

		private List<FileInformation> UpdateList(List<FileInformation> list)
		{
			return AddFileInList(source, list);
		}

		/// <summary>
		/// Получение списка файлов для копирования.
		/// </summary>
		/// <returns>Список файлов для копирования типа FileInformation</returns>
		public List<FileInformation> GetListForCopy()
		{
			filesInSourceDir = UpdateList(filesFromRelease);
			List<FileInformation> filesForCopy = this.filesInSourceDir;

			if (Directory.Exists(target))
			{
                List<FileInformation> filesInTargetDir = new Ignorer(target, excludeFolders).GetFiles().Select(p => new FileInformation(p, Utils.ComputeMd5Checksum(p.FullName))).ToList();
				foreach (FileInformation fileInTarget in filesInTargetDir)
				{
					FileInformation fileForRemove = filesForCopy.Find(p => p.Hash == fileInTarget.Hash);
					if (fileForRemove != null)
					{
						filesForCopy.Remove(fileForRemove);
					}
				}
			}

			return filesForCopy;
		}

		private List<FileInformation> AddFileInList(string dir, List<FileInformation> list = null)
		{
			if (Directory.Exists(dir))
			{
				var directory = new DirectoryInfo(dir);
				List<FileInfo> listFileInSource = directory.GetFiles(".", SearchOption.AllDirectories).ToList();

				if (list == null)
				{
					return listFileInSource.Select(file => new FileInformation(file, Utils.ComputeMd5Checksum(file.FullName))).ToList();
				}

				List<string> inSource = listFileInSource.Select(info => info.FullName).ToList();
				List<string> inList = list.Select(info => info.FileInfo.FullName).ToList();
				List<FileInformation> result = inSource.Except(inList).Select(s => new FileInformation(new FileInfo(s), Utils.ComputeMd5Checksum(s))).ToList();
				list.AddRange(result);
			    var templist = list.Where(p => !p.FileInfo.Exists).ToList();

                if (templist.Count != 0)
                {
                    throw new SynchronizerException(SynchronizerException.ErrorType.ChackSummFileInvalid);
                }

				return list;
			}

			return new List<FileInformation>();
		}
	}
}
